// 问题：如果 then 方法返回的是自己的 Promise 对象，则会发生循环调用，这个时候程序正常是需要报错，但是 MyPromise 并没有报错
// 解决：1. 在 then() 中判断如果返回的是自己的 Promise 对象，则 reject() 抛错
//          --- 直接判断抛错，程序报错：
//              ReferenceError: Cannot access 'p2' before initialization
//              --- 原因：此时 p2 初始化，还没有返回，无法使用它去做判断
//      2. 创建一个微任务等待 promise2 完成初始化

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

/**
 *
 *
 * @class MyPromise
 */
class MyPromise {
    constructor(executor) {
        executor(this.resolve, this.reject)
    }
    status = PENDING

    value = null
    reason = null

    onFulfilledCallbacks = []
    onRejectedCallbacks = []

    resolve = (value) => {
        if (this.status === PENDING) {
            this.status = FULFILLED
            this.value = value
            while(this.onFulfilledCallbacks.length) {
                this.onFulfilledCallbacks.shift()(value)
            }
        }
    }
    reject = (reason) => {
        if (this.status === PENDING) {
            this.status = REJECTED
            this.reason = reason
            while(this.onRejectedCallbacks.length) {
                this.onRejectedCallbacks.shift()(reason)
            }
        }
    }

    then = (onFulfilled, onRejected) => {
        // 将创建的promise实例保存下来，用于做判断
        const p2 = new MyPromise((resolve, reject) => {
            if (this.status === FULFILLED) {    // 上一个 MyPromise 的状态为Fulfilled
                // 2. 创建一个微任务等待 promise2 完成初始化
                queueMicrotask(() => {
                    const x = onFulfilled(this.value)
                    resolvePromise(p2, x, resolve, reject)
                })
                
            }
            else if (this.status === REJECTED) {
                onRejected(this.reason)
            } 
            else {
                this.onFulfilledCallbacks.push(onFulfilled)
                this.onRejectedCallbacks.push(onRejected)
            }
        })
        return p2
    }
}
function resolvePromise(p2, x, resolve, reject) {
    if (x instanceof MyPromise) {
        if (x === p2) { // 1. 在 then() 中判断如果返回的是自己的 Promise 对象，则 reject() 抛错
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        } else {
            x.then(resolve, reject)
        }
    } else {
        resolve(x)
    }
}

console.log(`--------------- 链式调用 返回promise自己时，需要报错 ------------------`)
const promise = new MyPromise((resolve, reject) => {
    resolve(`promise resolve: success`)
})
const promise1 = promise.then(value => {
    console.log(value)
    return promise1
})
promise1.then(value => {
    console.log(value)
},
reason => {
    console.log(reason)
})

console.log(`--------------- 链式调用 返回promise自己时，需要报错 ------------------`)
const promise2 = new MyPromise((resolve, reject) => {
    throw new Error('执行器错误')
    resolve(`promise2 resolve: success`)
})
promise2.then(value => {
    console.log(value)
},
reason => {
    console.log(reason)
})